package com.zhimeng.personal.activities;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.zhimeng.personal.R;
import com.zhimeng.personal.data.DataCenter;
import com.zhimeng.personal.http.RequestParams;
import com.zhimeng.personal.interfaces.MarkerCardCallback;
import com.zhimeng.personal.models.Position;
import com.zhimeng.personal.models.User;
import com.zhimeng.personal.utils.BitmapUtils;
import com.zhimeng.personal.utils.DateUtils;
import com.zhimeng.personal.utils.DensityUtils;
import com.zhimeng.personal.utils.FileUtil;
import com.zhimeng.personal.utils.GlideUtils;
import com.zhimeng.personal.utils.ToastUtils;
import com.zhimeng.personal.utils.views.CardMarkerView;
import com.zhimeng.personal.utils.views.LocMarkerView;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by sunzhimeng on 10/31/17.
 */
public abstract class BaseMapActivity extends BaseActivity implements MarkerCardCallback, LocationSource, AMapLocationListener {
    public MapView mapView;
    public AMap aMap;
    public ArrayList<Position> positions;
    public List<Marker> mMarkerList;
    public final int UPDATE_CARD_NORMAL = 0;
    public final int UPDATE_CARD_SHADOW = 1;
    public Marker lastMarker = null;
    public Marker creatMarker;
    public Marker userMarker;
    //定位需要的声明
    private AMapLocationClient mLocationClient = null;//定位发起端
    private LocationSource.OnLocationChangedListener mListener = null;//定位监听器
    //标识，用于判断是否只显示一次定位信息和用户重新定位
    private boolean isFirstLoc = true;
    private MyLocationStyle myLocationStyle;
    private boolean isUserAvatarReady = false;
    public AMapLocation amapLocation;
    private View infoWindow;
    private LatLng lastLng;
    private SensorManager mSensorManager;
    private Sensor mASensor;
    private Sensor mMSensor;
    private View userMarkerView;
    float[] accelerometerValues = new float[3];
    float[] magneticFieldValues = new float[3];
    float[] values = new float[3];
    float floats;
    float[] R2 = new float[9];
    final SensorEventListener myListener = new SensorEventListener() {

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onSensorChanged(SensorEvent event) {
            // TODO Auto-generated method stub
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                accelerometerValues = event.values.clone();
            }
            if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                magneticFieldValues = event.values.clone();
            }
            if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
                floats = event.values[1];
            }

            //方向传感器
            // 调用getRotaionMatrix获得变换矩阵R[]
            SensorManager.getRotationMatrix(R2, null, accelerometerValues,
                    magneticFieldValues);
            SensorManager.getOrientation(R2, values);
            // 经过SensorManager.getOrientation(R, values);得到的values值为弧度
            // 转换为角度
            values[0] = (float) Math.toDegrees(values[0]);
//            values[2] = -values[2];
//            if (values[1] > 0) {
//                values[1] += 180;
//            }

            setMyMarkerStyleRotated(values[0]);


        }
    };

    private void setMyMarkerStyleRotated(float value) {
        if (isUserAvatarReady) {
            userMarkerView.setRotation(value);
        }
    }

    public void initBaseData() {
        positions = new ArrayList<>();
        mMarkerList = new ArrayList<>();
    }

    //展示标签
    public void showTags(List<Position> entities) {
        for (int i = 0; i < mMarkerList.size(); i++) {
            mMarkerList.get(i).remove();
        }
        mMarkerList.clear();
        positions.clear();
        if (entities.size() != 0) {
            for (int i = 0; i < entities.size(); i++) {
                showTag(entities.get(i), false);
            }
        } else {
            ToastUtils.showToast(getResources().getString(R.string.hint_no_related_tags));
        }
    }

    // 移除屏幕不可见标签
    public void removeInvisableEntities() {
        ArrayList<Position> mapTags = new ArrayList();

        for (int i = 0; i < aMap.getMapScreenMarkers().size(); i++) {
            if (aMap.getMapScreenMarkers().get(i).getObject() instanceof Position) {
                mapTags.add((Position) aMap.getMapScreenMarkers().get(i).getObject());
            }
        }
        if (positions.removeAll(mapTags)) {
            for (int i = 0; i < positions.size(); i++) {
                removeTag(positions.get(i));
                i--;
            }
        }
        positions = mapTags;
    }

    public Marker showTag(Position Position, boolean isSelected) {
        LatLng latlng = new LatLng(Position.getLatitude(), Position.getLongitude());
        Marker marker = aMap.addMarker(new MarkerOptions()
                .title(Position.getTitle())
                .position(latlng)
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_loc_inv))
                .draggable(true)); //方法中设置asBitmap可以设置回调类型
        marker.setObject(Position);
        showTag(marker, isSelected);
        return marker;
    }

    public void showTag(final Marker marker, final boolean isSelected) {
        if (marker != null && marker.getObject() != null) {
            final Position position = (Position) marker.getObject();
            String iconUrl = "";
            if (!positions.contains(position)) positions.add(position);
            if (aMap.getCameraPosition().zoom >= 15 && position.getThumbAvatar() != null) {
                iconUrl = position.getThumbAvatar();
            } else iconUrl = position.getThumbAvatar();
            GlideUtils.getInstance().downloadasBitmap(this, iconUrl, new GlideUtils.GlideDownloadCallback() {
                @Override
                public void handleBitmap(final Bitmap resource) {
                    if (!mMarkerList.contains(marker)) mMarkerList.add(marker);
                    final CardMarkerView markView = new CardMarkerView(BaseMapActivity.this);
                    GlideUtils.getInstance().downloadasBitmap(BaseMapActivity.this, position.getUser().getAvatarUrl(), new GlideUtils.GlideDownloadCallback() {
                        @Override
                        public void handleBitmap(Bitmap bitmap) {
                            markView.isMarkerSelected(isSelected);
                            markView.setFrontVeiw(resource);
                            markView.setAvatar(bitmap);
                            if (isSelected) {
                                lastMarker = marker;
                                Bitmap backgroudbitmap = BitmapUtils.convertViewToBitmap(markView);
                                marker.setIcon(BitmapDescriptorFactory.fromBitmap(BitmapUtils.scaleBitmap(backgroudbitmap, 1.0f, 1.0f)));
                            } else {
                                marker.setIcon(BitmapDescriptorFactory.fromView(markView));
                            }
                        }
                    });
                }
            });

        }
    }

    //获取当前位置并赋值
    public void getLocation(RequestParams param) {
        if (aMap != null) {
            LatLng latLng = aMap.getCameraPosition().target;
            float zoomLevel = aMap.getCameraPosition().zoom;
            param.put("latitude", latLng.latitude);
            param.put("longitude", latLng.longitude);
            param.put("level", zoomLevel);

        }
    }

    public String getLocation() {
        String location = "";
        if (aMap != null) {
            LatLng latLng = aMap.getCameraPosition().target;
            location = latLng.longitude + "," + latLng.latitude;
        }
        return location;
    }


    /**
     * 初始化AMap对象
     */
    public void initBaseView() {

        if (aMap == null) {
            aMap = mapView.getMap();
            aMap.setMapCustomEnable(true);
            aMap.setCustomMapStylePath(FileUtil.getAmapThemeConfigFile(this));
        }

        //设置定位监听
        aMap.setLocationSource(this);
        //开始定位
        initLoc();
//        setLocationStyle(BitmapDescriptorFactory.fromResource(R.mipmap.bg_user_marker_loc));
        aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示，非必需设置。
        aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
        aMap.getUiSettings().setZoomControlsEnabled(false);
        aMap.showMapText(true);//设置显示文字
//        aMap.getUiSettings().setCompassEnabled(true);//设置打开指南针
        //地图加载完成回调
        aMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
            @Override
            public void onMapLoaded() {
                CameraUpdate cu = CameraUpdateFactory.zoomTo(15);
                aMap.moveCamera(cu);
            }
        });
        //地图改变回调
        aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDragStart(Marker marker) {
                removeTag((Position) marker.getObject());
                Marker marker1 = showTag((Position) marker.getObject(), true);
                onMarkerLongClick(marker1);
            }

            @Override
            public void onMarkerDrag(Marker marker) {

            }

            @Override
            public void onMarkerDragEnd(Marker marker) {

            }
        });
        aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
            @Override
            public View getInfoWindow(Marker marker) {
                if (infoWindow == null) {
                    infoWindow = LayoutInflater.from(BaseMapActivity.this).inflate(
                            R.layout.layout_marker_info_window, null);
                }
                renderWindow(marker, infoWindow);

                return infoWindow;
            }

            @Override
            public View getInfoContents(Marker marker) {
                return null;
            }
        });
    }

    private void setLocationStyle(BitmapDescriptor icon) {
        myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
        myLocationStyle.myLocationIcon(icon);
        myLocationStyle.radiusFillColor(Color.parseColor("#45A1A1FF"));
        myLocationStyle.strokeColor(Color.parseColor("#A1A1FF"));
        myLocationStyle.strokeWidth(1);
        myLocationStyle.interval(5000); //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
        if (aMap != null) aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
    }

    protected void renderWindow(Marker marker, View window) {
        TextView infoText = (TextView) window.findViewById(R.id.tv_info);
        infoText.setText(DateUtils.getCurrentDateFormat() + marker.getTitle());
    }

    public abstract void onMarkerLongClick(Marker marker);

    public void showTouchPin(LatLng lng) {
        creatMarker = aMap.addMarker(new MarkerOptions()
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_red_pin))
                .position(lng)
                .draggable(false)); //方法中设置asBitmap可以设置回调类型
        creatMarker.setObject(true);
        updateCreatMakerInfo();
    }

    public void updateCreatMakerInfo() {
        creatMarker.hideInfoWindow();
        getAddressByLatlng(creatMarker.getPosition(), new AddressSearchCallback() {
            @Override
            public void onAddressGetted(String address) {
                //            creatMarker.showInfoWindow();
            }
        });
    }

    //定位
    public void initLoc() {
        //初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        //设置定位回调监听
        mLocationClient.setLocationListener(this);
        //初始化定位参数
        AMapLocationClientOption locationOption = new AMapLocationClientOption();
        //设置定位模式为高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
        locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置是否返回地址信息（默认返回地址信息）
        locationOption.setNeedAddress(true);
        //设置是否只定位一次,默认为false
        locationOption.setOnceLocation(false);
        //设置是否强制刷新WIFI，默认为强制刷新
        locationOption.setWifiActiveScan(true);
        //设置是否允许模拟位置,默认为false，不允许模拟位置
        locationOption.setMockEnable(false);
        //设置定位间隔,单位毫秒,默认为2000ms
        locationOption.setInterval(5000);
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(locationOption);
        //启动定位
        mLocationClient.startLocation();

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mASensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
//        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);陀螺仪
        initUserMarker();
        mSensorManager.registerListener(myListener, mASensor,
                SensorManager.SENSOR_DELAY_GAME);
        mSensorManager.registerListener(myListener, mMSensor,
                SensorManager.SENSOR_DELAY_GAME);

    }

    private void initUserMarker(){
        userMarkerView = View.inflate(this, R.layout.loc_user_marker_layout, null);
        final ImageView avatar = (ImageView) userMarkerView.findViewById(R.id.iv_avatar);
        GlideUtils.getInstance().downloadasBitmap(this, DataCenter.getCurrentUser().getAvatarUrl(), new GlideUtils.GlideDownloadCallback() {
            @Override
            public void handleBitmap(Bitmap bitmap) {
                avatar.setImageBitmap(BitmapUtils.getCircleBitmap(bitmap));
                isUserAvatarReady = true;
                setLocationStyle(BitmapDescriptorFactory.fromBitmap(BitmapUtils.getBitmapFromView(userMarkerView)));
            }
        });
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onResume() {
        super.onResume();
        if (hasMap()) {
            mapView.onResume();
//            if (userMarker == null) {
//                showUserMarker(DataCenter.getCurrentLocation());
//            }
        }
    }

    private boolean hasMap() {
        return mapView != null;
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onPause() {
        super.onPause();
        if (hasMap())
            mapView.onPause();
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (hasMap())
            mapView.onSaveInstanceState(outState);
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (hasMap()) {
            mapView.onDestroy();
        }
        mLocationClient.unRegisterLocationListener(this);
//        System.exit(0);
    }

    //高亮显示选择标记
    public void highlightSelectMarker(Marker marker) {
        if (lastMarker != null) {
            unSelectTag(lastMarker);
        }
        showTag(marker, true);
        if (!aMap.getMapScreenMarkers().contains(marker)) {
            aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(marker.getPosition().latitude, marker.getPosition().longitude)));
        }
        lastMarker = marker;
    }

    //高亮显示选择标记
    public void highlightSelectTag(Position Position) {
        for (int i = 0; i < mMarkerList.size(); i++) {
            if (((Position) mMarkerList.get(i).getObject()).getId() == Position.getId()) {
                highlightSelectMarker(mMarkerList.get(i));
            }
        }
    }

    @Override
    public void initViews(Bundle savedInstanceState) {
        mapView = (MapView) findViewById(R.id.map);
        mapView.onCreate(savedInstanceState);// 此方法必须重写
        initBaseView();
        initBaseData();
    }

    public void unSelectTag(Marker marker) {
        showTag(marker, false);
    }

    public void goToRegister() {
        startActivity(new Intent(this, RegisterActivity.class));
    }

    public void selectMarker(Position Position) {
        for (Marker marker : mMarkerList) {
            if (((Position) marker.getObject()).getId() == Position.getId()) {
                highlightSelectMarker(marker);
                marker.setToTop();
            }
        }
    }

    @Override
    public void activate(LocationSource.OnLocationChangedListener listener) {
        mListener = listener;
    }

    @Override
    public void deactivate() {
        mListener = null;
    }

    @Override
    public void onLocationChanged(AMapLocation amapLocation) {
        if (amapLocation != null) {
            if (amapLocation.getErrorCode() == 0) {
                //定位成功回调信息，设置相关消息
                amapLocation.getLocationType();//获取当前定位结果来源，如网络定位结果，详见官方定位类型表
                amapLocation.getLatitude();//获取纬度
                amapLocation.getLongitude();//获取经度
                amapLocation.getAccuracy();//获取精度信息
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date(amapLocation.getTime());
                df.format(date);//定位时间
                amapLocation.getAddress();//地址，如果option中设置isNeedAddress为false，则没有此结果，网络定位结果中会有地址信息，GPS定位不返回地址信息。
                amapLocation.getCountry();//国家信息
                amapLocation.getProvince();//省信息
                amapLocation.getCity();//城市信息
                amapLocation.getDistrict();//城区信息
                amapLocation.getStreet();//街道信息
                amapLocation.getStreetNum();//街道门牌号信息
                amapLocation.getCityCode();//城市编码
                amapLocation.getAdCode();//地区编码
                this.amapLocation = amapLocation;
                // 如果不设置标志位，此时再拖动地图时，它会不断将地图移动到当前的位置
                LatLng location = new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude());
                DataCenter.setCurrentLocation(location);
                DataCenter.setCurrentAddress(amapLocation.getCity() + amapLocation.getDistrict());
                if (isFirstLoc) {
                    if (hasMap()) {
                        //设置缩放级别
                        aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
                        //将地图移动到定位点
                        aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude())));
                        //点击定位按钮 能够将地图的中心移动到定位点
                    }
                    if (mListener != null)
                        mListener.onLocationChanged(amapLocation);
                    isFirstLoc = false;
                }
                //添加图钉

//                if (userMarker == null || (isActvityVisible() && isNeedReDrawUser(location))) {
//                    showUserMarker(location);
//                } else {
//                    userMarker.setToTop();
//                }

            } else {
                //显示错误信息ErrCode是错误码，errInfo是错误信息，详见错误码表。
                Log.e("AmapError", "location Error, ErrCode:"
                        + amapLocation.getErrorCode() + ", errInfo:"
                        + amapLocation.getErrorInfo());
                ToastUtils.showToast(R.string.setting_location);
            }
        }
    }

    private boolean isNeedReDrawUser(LatLng lng) {
        if (lastLng == null) return true;
        Point point1 = aMap.getProjection().toScreenLocation(lastLng);
        Point point2 = aMap.getProjection().toScreenLocation(lng);
        return Math.pow((point2.x - point1.x), 2) + Math.pow((point2.y - point1.y), 2) > DensityUtils.dp2px(this, 9);
    }

    public void showUserMarker(final LatLng location) {
        if (DataCenter.isSigned() && hasMap()) {
            final User user = DataCenter.getCurrentUser();
            Glide.with(this).load(user.getAvatarUrl())
                    .asBitmap().into(new SimpleTarget<Bitmap>() {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                    LocMarkerView markView = new LocMarkerView(BaseMapActivity.this);
                    markView.setFrontVeiw(BitmapUtils.getCircleBitmap(BitmapUtils.centerSquareScaleBitmap(resource)));
                    markView.isMarkerSelected(true);
                    if (userMarker != null) {
                        userMarker.remove();
                    }
                    userMarker = aMap.addMarker(new MarkerOptions()
                            .title(user.getName())
                            .position(location)
                            .anchor(0.5f, 0.5f)
                            .draggable(false));
                    userMarker.setIcon(BitmapDescriptorFactory.fromView(markView)); //方法中设置asBitmap可以设置回调类型
                    userMarker.setToTop();
                    userMarker.setObject(user);
                    lastLng = location;
                }
            });
        }
    }


    public void updateCard(Position Position, Point point) {

        LatLng target = aMap.getProjection()
                .fromScreenLocation(point);
        updateCard(Position, target);

    }

    public void updateCard(Position Position, LatLng target) {
        updateCard(Position, target, 0);
    }

    public void updateCard(Position Position, LatLng target, int code) {
        RequestParams param = new RequestParams();
        param.put("coordinate", target.longitude + "," + target.latitude);
        param.put("shadow", code);
        // request code
    }

    public void removeTag(Position Position) {
        for (int i = 0; i < mMarkerList.size(); i++) {
            if (((Position) mMarkerList.get(i).getObject()).getId() == Position.getId()) {
                Marker marker = mMarkerList.get(i);
                mMarkerList.remove(i);
                marker.remove();
                positions.remove(Position);
                i--;
            }
        }

    }

    public void moveCameraToLocation() {
        //将地图移动到定位点
        aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude())));
    }

    public void moveCameraToLocation(LatLng latLng) {
        //将地图移动到定位点
        aMap.moveCamera(CameraUpdateFactory.changeLatLng(latLng));
    }

    public void fixCreatCardPin(LatLng lng, int position) {
        aMap.moveCamera(CameraUpdateFactory.scrollBy(0, position));
        Point screenPosition = aMap.getProjection().toScreenLocation(lng);
        creatMarker.setPositionByPixels(screenPosition.x, screenPosition.y - position);
    }

    public Point getPinScreenPosition() {
        return aMap.getProjection().toScreenLocation(creatMarker.getPosition());
    }

    public void findTagOnMap(Position entity) {
        for (int i = 0; i < positions.size(); i++) {
            if (positions.get(i).getId() == entity.getId()) {
                removeTag(positions.get(i));
                break;
            }
        }
        unSelectTag(lastMarker);
        showTag(entity, true);
        moveCameraToLocation(entity.getLocation());
    }
}
